﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LiteExpress.Utilities
{
    public class DbHelper
    {
        public static DataRow ToDataRow(IDataReader reader, DataTable dt = null)
        {
            if (reader == null || reader.IsClosed)
            {
                return null;
            }

            // You can also use an ArrayList instead of List<>
            List<DataColumn> listCols = new List<DataColumn>();
            if (dt == null)
            {
                DataTable dtSchema = reader.GetSchemaTable();
                dt = new DataTable();

                if (dtSchema != null)
                {
                    foreach (DataRow drow in dtSchema.Rows)
                    {
                        string columnName = System.Convert.ToString(drow["ColumnName"]);
                        DataColumn column = new DataColumn(columnName, (Type)(drow["DataType"]));
                        column.Unique = (bool)drow["IsUnique"];
                        column.AllowDBNull = (bool)drow["AllowDBNull"];
                        column.AutoIncrement = (bool)drow["IsAutoIncrement"];
                        listCols.Add(column);
                        dt.Columns.Add(column);
                    }
                }
            }
            // Read rows from DataReader and populate the DataTable
            DataRow dataRow = dt.NewRow();
            for (int i = 0; i < listCols.Count; i++)
            {
                dataRow[((DataColumn)listCols[i])] = reader[i];
            }
            return dataRow;
        }

        /// <summary>
        /// 使用datareader填充datable
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="withdata">是否获取数据，否则只获取表结构</param>
        /// <returns></returns>
        public static DataTable CopySchemeToDataTable(IDataReader reader, bool withdata = false)
        {
            if (reader == null || reader.IsClosed)
            {
                return null;
            }

            DataTable dtSchema = reader.GetSchemaTable();
            DataTable dt = new DataTable();
            // You can also use an ArrayList instead of List<>
            List<DataColumn> listCols = new List<DataColumn>();

            if (dtSchema != null)
            {
                foreach (DataRow drow in dtSchema.Rows)
                {
                    string columnName = System.Convert.ToString(drow["ColumnName"]);
                    DataColumn column = new DataColumn(columnName, (Type)(drow["DataType"]));
                    column.Unique = (bool)drow["IsUnique"];
                    column.AllowDBNull = (bool)drow["AllowDBNull"];
                    column.AutoIncrement = (bool)drow["IsAutoIncrement"];
                    listCols.Add(column);
                    dt.Columns.Add(column);
                }
            }

            if (withdata)
            {
                // Read rows from DataReader and populate the DataTable
                while (reader.Read())
                {
                    DataRow dataRow = dt.NewRow();
                    for (int i = 0; i < listCols.Count; i++)
                    {
                        dataRow[((DataColumn)listCols[i])] = reader[i];
                    }
                    dt.Rows.Add(dataRow);
                }
            }
            return dt;
        }

        /// <summary>
        /// 批量插入
        /// </summary>
        /// <param name="conn">数据库连接</param>
        /// <param name="table">目标表名</param>
        /// <param name="data">目标数据</param>
        /// <param name="bulkTimeout">每批数据超时时间</param>
        /// <param name="batchSize">每批数据条数</param>
        public static void BlockCopy(System.Data.SqlClient.SqlConnection conn, string table, DataTable data, TimeSpan bulkTimeout = new TimeSpan(), int batchSize = 500)
        {
            if (bulkTimeout.TotalSeconds == 0)
            {
                bulkTimeout = new TimeSpan(0, 5, 0);
            }

            using (var sbc = new System.Data.SqlClient.SqlBulkCopy(conn)
            {
                BulkCopyTimeout = (int)bulkTimeout.TotalSeconds,
                NotifyAfter = data.Rows.Count,
                BatchSize = 500,
                DestinationTableName = table
            })
            {
                if (conn.State != ConnectionState.Open)
                {
                    conn.Open();
                }
                foreach (DataColumn column in data.Columns)
                    sbc.ColumnMappings.Add(column.ColumnName, column.ColumnName);
                sbc.WriteToServer(data);
            }
            conn.Close();
        }

        /// <summary>
        /// 通过list构造datable，返回的表字段名与类属性名保持一致
        /// </summary>        
        public static DataTable ParseToDataTable<T>(IEnumerable<T> list)
        {
            Type itemType = typeof(T);
            var pros = itemType.GetProperties();            

            var ret = new DataTable();
            foreach (var pro in pros)
            {
                ret.Columns.Add(pro.Name, pro.PropertyType);
            }
            
            foreach (var item in list)
            {
                ret.Rows.Add(pros.Select(p => p.GetValue(item)).ToArray());
            }
            return ret;
        }
    }
}
